home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Suzy B Software 2
/
Suzy B Software CD-ROM 2 (1994).iso
/
extras
/
programm
/
gemfsc20
/
gemfsc20.lzh
/
GEMFUNCS
/
OBJTSCRO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-03-20
|
22KB
|
595 lines
/*****************************************************************************
*
****************************************************************************/
#include "gemfintl.h"
#define SCL_DATA_SLL 0x0001
#define SCL_DATA_DLL 0x0002
#define SCL_DRAG_UPDATE 0x0100
static OBJECT scroll_tree[] = {
{ -1, 1, 6, G_IBOX, NONE, NORMAL, (_Ob_spec_t)0x00FF1181L, 0x0000, 0x0000, 0x0000, 0x0000},
{ 6, 2, 5, G_IBOX, NONE, NORMAL, (_Ob_spec_t)0x00001181L, 0x0000, 0x0000, 0x0000, 0x0000},
{ 3, -1, -1, G_BOXCHAR, NONE, NORMAL, (_Ob_spec_t)0x01FF1181L, 0x0000, 0x0000, 0x0000, 0x0000},
{ 5, 4, 4, G_BOX, NONE, NORMAL, (_Ob_spec_t)0x00FF1191L, 0x0000, 0x0000, 0x0000, 0x0000},
{ 3, -1, -1, G_BOX, NONE, NORMAL, (_Ob_spec_t)0x00FF1181L, 0x0000, 0x0000, 0x0000, 0x0000},
{ 1, -1, -1, G_BOXCHAR, NONE, NORMAL, (_Ob_spec_t)0x02FF1181L, 0x0000, 0x0000, 0x0000, 0x0000},
{ 0, 7, 22, G_IBOX, NONE, NORMAL, (_Ob_spec_t)0x00001181L, 0x0000, 0x0000, 0x0000, 0x0000},
{ 8, -1, -1, G_RSTRING, NONE, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x0000, 0x0000, 0x0001},
{ 9, -1, -1, G_RSTRING, NONE, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x0001, 0x0000, 0x0001},
{ 10, -1, -1, G_RSTRING, NONE, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x0002, 0x0000, 0x0001},
{ 11, -1, -1, G_RSTRING, NONE, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x0003, 0x0000, 0x0001},
{ 12, -1, -1, G_RSTRING, NONE, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x0004, 0x0000, 0x0001},
{ 13, -1, -1, G_RSTRING, NONE, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x0005, 0x0000, 0x0001},
{ 14, -1, -1, G_RSTRING, NONE, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x0006, 0x0000, 0x0001},
{ 15, -1, -1, G_RSTRING, NONE, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x0007, 0x0000, 0x0001},
{ 16, -1, -1, G_RSTRING, NONE, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x0008, 0x0000, 0x0001},
{ 17, -1, -1, G_RSTRING, NONE, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x0009, 0x0000, 0x0001},
{ 18, -1, -1, G_RSTRING, NONE, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x000A, 0x0000, 0x0001},
{ 19, -1, -1, G_RSTRING, NONE, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x000B, 0x0000, 0x0001},
{ 20, -1, -1, G_RSTRING, NONE, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x000C, 0x0000, 0x0001},
{ 21, -1, -1, G_RSTRING, NONE, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x000D, 0x0000, 0x0001},
{ 22, -1, -1, G_RSTRING, NONE, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x000E, 0x0000, 0x0001},
{ 6, -1, -1, G_RSTRING, LASTOB, NORMAL, (_Ob_spec_t)NULL, 0x0000, 0x000F, 0x0000, 0x0001}
};
#define SCROLL_CONTROLS 1
#define SCROLL_UPARROW 2
#define SCROLL_PAGE 3
#define SCROLL_SLIDER 4
#define SCROLL_DOWNARROW 5
#define DATA_AREA 6
#define FIRST_DATA_LINE 7
#define MIN_DATA_CHARS 4
#define MIN_DATA_LINES 5
#define MAX_DATA_LINES 16
#define DATA_AREA_WGUTTER (gl_w2char+gl_w4char)
#define DATA_AREA_HGUTTER (gl_h2char)
#define SCROLL_CONTROL_WIDTH ((2*gl_wchar) + gl_w2char)
#define SCROLL_ARROW_HEIGHT (gl_hchar + gl_h4char)
#define MIN_SCROLLOBJ_WIDTH (SCROLL_CONTROL_WIDTH+(MIN_DATA_CHARS*gl_wchar)+(2*DATA_AREA_WGUTTER))
#define MIN_SCROLLOBJ_HEIGHT ((MIN_DATA_LINES*gl_hchar)+(2*DATA_AREA_HGUTTER))
#define MAX_SCROLLOBJ_HEIGHT ((MAX_DATA_LINES*gl_hchar)+(2*DATA_AREA_HGUTTER))
/*----------------------------------------------------------------------------
*
*--------------------------------------------------------------------------*/
typedef struct tscroll_info {
XUSERBLK xub; /* standard XUSERDEF header */
void *datalist; /* pointer to data to show in scroller */
short numitems; /* number of items in data list */
short curitem; /* index of currently selected item */
short topitem; /* index of item displayed on top line */
short flags; /* processing flags */
short numlines; /* number of lines in the scroller window*/
short statusobj; /* obj in main tree that shows cur selection*/
GRECT dialog_rectangles[7]; /* rectangles describing scroller */
} TSCROLLINFO;
static char nullstr[] = ""; /* empty string for unused data lines */
/*----------------------------------------------------------------------------
* internal functions...
*--------------------------------------------------------------------------*/
#ifdef GEMFAST_PROTOS
INTERNAL_VFUNC init_scroll_tree(void);
INTERNAL_VFUNC update_tree_from_scrollinfo(TSCROLLINFO *pinfo);
INTERNAL_VFUNC render_scroller(TSCROLLINFO *pinfo, GRECT *cliprect);
INTERNAL_VFUNC continuous_scroll(TSCROLLINFO *pinfo, short scrollobj, short mx, short my);
INTERNAL_IFUNC count_items(void *datalist);
static void GCALLBACK udscroll(OBJECT *ptree, short obj, short slidepos, void *udata);
static XUBT_STATUS GCALLBACK feel_scroller(XUSERBLK *xub, short mx, short my, short clicks);
#endif
INTERNAL_VFUNC init_scroll_tree()
/*****************************************************************************
* one-time init, set y and height of all data lines in scroll tree.
* this is essentially in place of doing rsrc_obfix() calls on the tree.
* we calc all the xywh values on the fly except for the data lines which
* don't move in relation to their parent no matter what else is happening,
* so here we do the obfix-style fixup for the data lines.
****************************************************************************/
{
short hchar = gl_hchar;
OBJECT *pobj = &scroll_tree[FIRST_DATA_LINE];
do {
pobj->ob_y *= hchar;
pobj->ob_height *= hchar;
} while (!((pobj++)->ob_flags & LASTOB));
}
INTERNAL_VFUNC update_tree_from_scrollinfo(pinfo)
TSCROLLINFO *pinfo;
/*****************************************************************************
* update the scroller dialog tree with values from the specified scroller.
****************************************************************************/
{
short i;
short item;
short linewidth;
char **strings;
OBJECT *pobj;
short slidesize;
short slidepos;
long pixel_range;
/*------------------------------------------------------------------------
* call lib routine to calc size & position of scroller. returned
* values are in the range 1-1000, or -1 for minimum-sized slider.
*----------------------------------------------------------------------*/
wc_scroll_calc(pinfo->topitem, pinfo->numitems, pinfo->numlines,
&slidesize, &slidepos);
/*------------------------------------------------------------------------
* translate position and size into actual x/y/w/h values.
*----------------------------------------------------------------------*/
pixel_range = pinfo->dialog_rectangles[SCROLL_PAGE].g_h;
slidesize = (short)((pixel_range * slidesize) / 1000L);
if (slidesize < gl_hchar) {
slidesize = gl_hchar;
}
slidepos = (short)(((pixel_range-slidesize) * slidepos) / 1000L);
pinfo->dialog_rectangles[SCROLL_SLIDER].g_y = slidepos;
pinfo->dialog_rectangles[SCROLL_SLIDER].g_h = slidesize;
/*------------------------------------------------------------------------
* set the dialog's controlling rectangles to scroller's values.
*----------------------------------------------------------------------*/
pobj = scroll_tree;
for (i = 0; i < Array_els(pinfo->dialog_rectangles); ++i) {
*(GRECT *)&pobj->ob_x = pinfo->dialog_rectangles[i];
++pobj;
}
/*------------------------------------------------------------------------
* set string pointers in the visible area of the scroller dialog.
*----------------------------------------------------------------------*/
strings = (char **)pinfo->datalist;
item = pinfo->topitem;
linewidth = pinfo->dialog_rectangles[DATA_AREA].g_w;
for (i = 0; i < MAX_DATA_LINES; ++i) {
if (i >= pinfo->numlines) { /* line isn't in visible area */
pobj->ob_flags |= HIDETREE; /* of scroller, hide it. */
} else {
pobj->ob_flags &= ~HIDETREE; /* line is visible, unhide it. */
pobj->ob_width = linewidth; /* set line object width. */
if (item >= pinfo->numitems) { /* if we're out of lines (short */
pobj->ob_spec = (_Ob_spec_t)nullstr; /* data list), show an empty line.*/
} else {
pobj->ob_spec = (_Ob_spec_t)(strings[item]);
}
pobj->ob_state = (item == pinfo->curitem) ? SELECTED : NORMAL;
++item;
}
++pobj;
}
}
INTERNAL_VFUNC render_scroller(pinfo, cliprect)
TSCROLLINFO *pinfo;
GRECT *cliprect;
/*****************************************************************************
* update the scroller visuals (controls, data area), then paint it.
****************************************************************************/
{
update_tree_from_scrollinfo(pinfo);
obj__draw(scroll_tree, ROOT, MAX_DEPTH, cliprect);
}
static long GCALLBACK see_scroller(pb)
XPARMBLK *pb;
/*****************************************************************************
* USERDEF drawing routine for scroller objects.
****************************************************************************/
{
TSCROLLINFO *pinfo = (TSCROLLINFO *)pb->pub;
pinfo->dialog_rectangles[0].g_x = pb->drawrect.g_x;
pinfo->dialog_rectangles[0].g_y = pb->drawrect.g_y;
render_scroller(pinfo, &pb->cliprect);
return 0;
}
static void GCALLBACK udscroll(ptree, obj, slidepos, udata)
OBJECT *ptree;
short obj;
short slidepos;
void *udata;
/*****************************************************************************
* the callback for grf_udslidebox() -- update window based on slider
****************************************************************************/
{
TSCROLLINFO *pinfo = udata;
if (slidepos > 2000) {
slidepos -= 2000;
} else if (slidepos > 1000) {
slidepos -= 1000;
}
pinfo->topitem = (short)((slidepos * (pinfo->numitems - pinfo->numlines)) / 1000L);
render_scroller(pinfo, &gl_rwdesk);
}
INTERNAL_VFUNC continuous_scroll(pinfo, scrollobj, mx, my)
TSCROLLINFO *pinfo;
short scrollobj;
short mx;
short my;
/*****************************************************************************
* continuously scroll the scroller object until mouse button released.
****************************************************************************/
{
short mb;
short slidey;
short dmy;
short scrollamt;
short newtop;
if (scrollobj == SCROLL_SLIDER) {
grf_udslidebox(scroll_tree, SCROLL_SLIDER, TRUE, udscroll, pinfo);
return;
} else {
switch (scrollobj) {
case SCROLL_UPARROW:
scrollamt = -1;
break;
case SCROLL_DOWNARROW:
scrollamt = 1;
break;
case SCROLL_PAGE:
objc_offset(scroll_tree, SCROLL_SLIDER, &dmy, &slidey);
if (my < slidey) {
scrollamt = -(pinfo->numlines);
} else {
scrollamt = pinfo->numlines;
}
break;
}
}
do {
newtop = pinfo->topitem + scrollamt;
if ((newtop + pinfo->numlines) > pinfo->numitems) {
newtop = pinfo->numitems - pinfo->numlines;
}
if (newtop < 0) {
newtop = 0;
}
if (pinfo->topitem != newtop || scrollamt == 0) {
pinfo->topitem = newtop;
render_scroller(pinfo, &gl_rwdesk);
}
graf_mkstate(&dmy, &dmy, &mb, &dmy);
} while (mb);
}
static XUBT_STATUS GCALLBACK feel_scroller(xub, mx, my, clicks)
XUSERBLK *xub;
short mx;
short my;
short clicks;
/*****************************************************************************
* routine to handle a click on a scroller object.
****************************************************************************/
{
short clickobj;
TSCROLLINFO *pinfo = (TSCROLLINFO *)xub;
XUBT_STATUS status;
update_tree_from_scrollinfo(pinfo);
clickobj = objc_find(scroll_tree, ROOT, MAX_DEPTH, mx, my);
if (clickobj <= ROOT || clickobj == DATA_AREA) {
status = XUBT_NONE;
} else if (DATA_AREA == obj_parent(scroll_tree, clickobj)) {
pinfo->curitem = pinfo->topitem + (clickobj - FIRST_DATA_LINE);
pinfo->xub.ob_spec = scroll_tree[clickobj].ob_spec;
update_tree_from_scrollinfo(pinfo);
obj__draw(scroll_tree, DATA_AREA, MAX_DEPTH, &gl_rwdesk);
if (pinfo->statusobj != NO_OBJECT) {
rsc_sstrings(xub->parent_tree, pinfo->statusobj, (char *)pinfo->xub.ob_spec, -1);
obj__draw(xub->parent_tree, pinfo->statusobj, MAX_DEPTH, &gl_rwdesk);
}
status = XUBT_VALUE;
if (clicks > 1) {
status |= XUBT_DCEXIT;
}
evn_wbutton(EVN_BUTTONUP);
} else {
continuous_scroll(pinfo, clickobj, mx, my);
status = XUBT_VISUAL;
}
return status;
}
INTERNAL_IFUNC count_items(datalist)
void *datalist;
/*****************************************************************************
*
****************************************************************************/
{
char **strings;
short numitems = 0;
for (strings = (char **)datalist; *strings != NULL; ++strings) {
++numitems;
}
return numitems;
}
/*----------------------------------------------------------------------------
* public functions...
*--------------------------------------------------------------------------*/
short obj_make_tscroll(ptree, obj, statusobj)
OBJECT *ptree;
short obj;
short statusobj;
/*****************************************************************************
*
****************************************************************************/
{
register OBJECT *pobj = &ptree[obj];
register TSCROLLINFO *pinfo;
if (scroll_tree[FIRST_DATA_LINE].ob_height == 1) {
init_scroll_tree(); /* do one-time init if not done already */
}
/*------------------------------------------------------------------------
* validate parms.
*----------------------------------------------------------------------*/
if (0 == apl_vshared()) {
return gfErr_vdi_handle;
}
if (pobj->ob_width < MIN_SCROLLOBJ_WIDTH ||
pobj->ob_height < MIN_SCROLLOBJ_HEIGHT) {
return gfErr_object_too_small;
}
if (pobj->ob_height > MAX_SCROLLOBJ_HEIGHT) {
return gfErr_object_too_big;
}
/*------------------------------------------------------------------------
* If the object has already been made into a G_TSCROLL extended object,
* just get its pointer, else make it into such an object.
*----------------------------------------------------------------------*/
if ((pobj->ob_type & 0x00FF) == G_USERDEF) {
pinfo = (TSCROLLINFO *)pobj->_Ob_spec;
if (pinfo->xub.ob_type != G_TSCROLL) {
return gfErr_wrong_type;
}
} else {
if (NULL == (pinfo = apl_malloc((long)sizeof(*pinfo)))) {
return gfErr_no_memory;
}
obj_mxuserdef(ptree, obj, &pinfo->xub, see_scroller, feel_scroller, (long)sizeof(*pinfo));
pinfo->xub.ob_type = G_TSCROLL;
pinfo->xub.ob_spec = (_Ob_spec_t)NULL;
}
pinfo->datalist = NULL;
pinfo->numitems = 0;
pinfo->curitem = NO_OBJECT;
pinfo->topitem = 0;
pinfo->flags = 0;
pinfo->statusobj = statusobj;
pinfo->numlines = (pobj->ob_height - (2 * DATA_AREA_HGUTTER)) / gl_hchar;
if (statusobj != NO_OBJECT) {
rsc_sstrings(ptree, statusobj, nullstr, -1);
}
/*------------------------------------------------------------------------
* build the rectangles describing the on-screen scroller.
*----------------------------------------------------------------------*/
#define SetRect(idx, x, y, w, h) \
pinfo->dialog_rectangles[idx].g_x = x; \
pinfo->dialog_rectangles[idx].g_y = y; \
pinfo->dialog_rectangles[idx].g_w = w; \
pinfo->dialog_rectangles[idx].g_h = h;
SetRect(ROOT,
pobj->ob_x,
pobj->ob_y,
pobj->ob_width,
pobj->ob_height);
SetRect(SCROLL_CONTROLS,
(pobj->ob_width - SCROLL_CONTROL_WIDTH),
0,
SCROLL_CONTROL_WIDTH,
pobj->ob_height);
SetRect(SCROLL_UPARROW,
0,
0,
SCROLL_CONTROL_WIDTH,
SCROLL_ARROW_HEIGHT);
SetRect(SCROLL_PAGE,
0,
SCROLL_ARROW_HEIGHT,
SCROLL_CONTROL_WIDTH,
(pobj->ob_height - 2 * SCROLL_ARROW_HEIGHT));
SetRect(SCROLL_SLIDER,
0,
0,
SCROLL_CONTROL_WIDTH,
1);
SetRect(SCROLL_DOWNARROW,
0,
(SCROLL_ARROW_HEIGHT + pinfo->dialog_rectangles[SCROLL_PAGE].g_h),
SCROLL_CONTROL_WIDTH,
SCROLL_ARROW_HEIGHT);
SetRect(DATA_AREA,
DATA_AREA_WGUTTER,
DATA_AREA_HGUTTER,
(pobj->ob_width - SCROLL_CONTROL_WIDTH - (2 * DATA_AREA_WGUTTER)),
(pobj->ob_height - (2 * DATA_AREA_HGUTTER)));
#undef SetRect
return 0;
}
void obj_set_tscroll(ptree, obj, datalist, numitems, curitem, topitem)
OBJECT *ptree;
short obj;
void *datalist;
short numitems;
short curitem;
short topitem;
/*****************************************************************************
*
****************************************************************************/
{
TSCROLLINFO *pinfo;
if (ptree[obj].ob_flags & INDIRECT) {
pinfo = *(TSCROLLINFO **)ptree[obj].ob_spec;
} else {
pinfo = (TSCROLLINFO *)ptree[obj].ob_spec;
}
if ((ptree[obj].ob_type & 0x00FF) != G_USERDEF) {
return;
}
if (pinfo->xub.ob_type != G_TSCROLL) {
return;
}
/*------------------------------------------------------------------------
* fill in the details in the scrollinfo structure...
*----------------------------------------------------------------------*/
if (datalist != NULL) {
pinfo->datalist = datalist;
pinfo->curitem = NO_OBJECT;
pinfo->topitem = 0;
if (numitems < 0) {
numitems = count_items(datalist);
}
}
if (numitems >= 0) {
pinfo->numitems = numitems;
}
if (curitem >= NO_OBJECT) {
if (curitem < pinfo->numitems) {
pinfo->curitem = curitem;
} else {
pinfo->curitem = NO_OBJECT;
}
}
if (topitem >= 0) {
if (topitem < pinfo->numitems) {
pinfo->topitem = topitem;
} else {
pinfo->topitem = 0;
}
}
if (pinfo->datalist == NULL || pinfo->curitem == NO_OBJECT) {
pinfo->xub.ob_spec = (_Ob_spec_t)NULL;
} else {
void **items = (void **)pinfo->datalist;
pinfo->xub.ob_spec = (_Ob_spec_t)items[pinfo->curitem];
}
if (pinfo->statusobj != NO_OBJECT) {
char *curstr;
if (pinfo->curitem == NO_OBJECT) {
curstr = nullstr;
} else {
curstr = (char *)pinfo->xub.ob_spec;
}
rsc_sstrings(ptree, pinfo->statusobj, curstr, -1);
}
}
short obj_get_tscroll(ptree, obj, curstring, curitem, topitem)
OBJECT *ptree;
short obj;
char **curstring;
short *curitem;
short *topitem;
/*****************************************************************************
*
****************************************************************************/
{
TSCROLLINFO *pinfo;
if (ptree[obj].ob_flags & INDIRECT) {
pinfo = *(TSCROLLINFO **)ptree[obj].ob_spec;
} else {
pinfo = (TSCROLLINFO *)ptree[obj].ob_spec;
}
if ((ptree[obj].ob_type & 0x00FF) != G_USERDEF) {
return NO_OBJECT;
}
if (pinfo->xub.ob_type != G_TSCROLL) {
return NO_OBJECT;
}
if (topitem != NULL) {
*topitem = pinfo->topitem;
}
if (curstring != NULL) {
*curstring = (char*)pinfo->xub.ob_spec;
}
if (curitem != NULL) {
*curitem = pinfo->curitem;
}
return pinfo->curitem;
}